(function($) {

	$.fn.quickquestions = function(config) {

		var defaults = {
			current : "one",
			questions : {
				'text' : 'welcome to quickquestions! please visit http://- to define questins.',
			},
			buttons : {
				'right' : {
					id : 'qq-button-right',
					movex : -100,
					movey : 0
				},
				'left' : {
					id : 'qq-button-left',
					movex : 100,
					movey : 0
				},
				'up' : {
					id : 'qq-button-up',
					movex : 0,
					movey : 100
				},
				'down' : {
					id : 'qq-button-down',
					movex : 0,
					movey : -100
				},
				'yes' : {
					id : 'qq-button-yes',
					movex : 0,
					movey : -100
				},
				'no' : {
					id : 'qq-button-no',
					movex : 0,
					movey : -100
				}
			}
		};

		var options = $.extend(defaults, config);
		var qc = options.current;
		var buttons = options.buttons;

		var parent_id = this[0].id;

		var refresh = function() {
			console.log('refreshing...');
			var q = options.questions;

			// error handling
			if (typeof q[qc] == 'undefined') {
				q[qc] = {
					'text' : 'Error: ' + qc + ' is not defined.'
				};
			}
			if (typeof q[qc]['text'] == 'undefined'
					&& typeof q[qc]['html'] == 'undefined') {
				q[qc] = {
					'text' : 'Error: text or html in ' + qc
							+ ' is not defined.'
				};
			}

			// message area
			if (typeof q[qc]['html'] != 'undefined') {
				$('#gq-q').html(execIfExists(q[qc]['html']));
			} else if (typeof q[qc]['text'] != 'undefined') {
				$('#gq-q').text(execIfExists(q[qc]['text']));
			}

			// show/hide buttons
			for ( var nm in buttons) {
				console.log(nm);

				var id = '#' + buttons[nm]['id'];
				if (typeof getNextQ(nm) == 'string') {
					$(id).show();
				} else {
					$(id).hide();
				}
			}

			// input area
			$("#gq-input-text").val(null);
			if (q[qc]['input'] == 'text') {
				$("#gq-input-text").show();
			} else {
				$("#gq-input-text").hide();
			}
			
			console.log('refreshing done.');
		};

		var getNextQ = function(direction) {
			console.log('getNextQ calling: qc=' + qc + ' direction='
					+ direction);
			var q = options.questions;

			if (typeof q[qc][direction] == 'undefined') {
				console.log('getNextQ undefined');
				return 0;
			}

			// console.log('getNextQ: next=' + q[qc][direction]);
			var n = execIfExists(q[qc][direction]);
			var n2 = execIfExists(q[qc][direction]['next']);
			if (typeof n == 'string') {
				// console.log(n);
				return n;
			} else if (typeof n2 == 'string') {
				// console.log(n2);
				return n2;
			} else {
				return 0;
			}
		};

		var click_button = function(event, ui, direction, movex, movey) {
			console.log('click_move calling.');
			var q = options.questions;

			var t = $(event.target);
			var id = t.attr('id');
			var gq_pos = $('#' + parent_id).position();

			console.log('click_move: ' + id);
			// console.log("left: " + gq_pos.left + ", top: " + gq_pos.top);

			// input
			if (typeof q[qc]['input'] != 'undefined') {
				if (q[qc]['input'] == 'text') {
					var n = $('#gq-input-text').val();
					console.log('input: ' + n);

					q[qc]['input-answer'] = n;
				}
			}

			// animation
			var a1 = {};
			var a2 = {};
			var a3 = {};
			a1['left'] = gq_pos.left + (movex);
			a1['top'] = gq_pos.top + (movey);
			a1['opacity'] = 0;
			a2['left'] = gq_pos.left - (movex);
			a2['top'] = gq_pos.top - (movey);
			a3['left'] = gq_pos.left;
			a3['top'] = gq_pos.top;
			a3['opacity'] = 1;

			$('#' + parent_id).animate(a1, 'slow').animate(a2, 0, function() {
				console.log('old qc: ' + qc);
				qc = getNextQ(direction);
				console.log('new qc: ' + qc);

				refresh();
			}).animate(a3, 'slow');
		};

		$("#gq-input-text")
				.keypress(
						function(e) {
							var t = $(this);
							var id = t.attr('id');

							var q = options.questions;
							var str_f = detoxifyValueForFunction(q[qc]['input-validation']['check']);
							var str_fs = detoxifyValueForFunction(q[qc]['input-validation']['success']);
							var str_fe = detoxifyValueForFunction(q[qc]['input-validation']['error']);

							eval('var f=(' + str_f + ')');
							eval('var fs=(' + str_fs + ')');
							eval('var fe=(' + str_fe + ')');
							if (f(e.charCode, e)) {
								// console.log('check returns ok ' + e.charCode);
								fs(e.charCode, e);
							} else {
								// console.log('check returns ng ' + e.charCode);
								fe(e.charCode, e);
								e.preventDefault();
							}
						});

		var detoxifyValueForFunction = function(v) {
			if (typeof v != 'string') {
				console.log('warn: no func found: ' + v);
			}
			if (v.substring(0, 8) != 'function') {
				console.log('warn: no func found: ' + v);
			}

			return v;
		};

		var execIfExists = function(t) {
			var q = options.questions;

			if (typeof t != 'string') {
				return t;
			}
			if (t.substring(0, 8) == 'function') {
				eval('var f=(' + t + ')');
				return f(q);
			}
			return t;
		};

		return {
			'init' : function() {
				console.log('init');
				console.log(options.questions);

				$.ajax({
					type : 'GET',
					async : false,
					scriptCharset : 'utf-8',
					dataType : 'json',
					url : options.questions,
					success : function(res) {
						console.log('success');
						console.log(res);
						options.questions = res;
					},
					error : function() {
						console.log('Miss..');
					}
				});

				// each button
				console.log('initializing buttons');
				$.each(buttons, function(i, v) {
					// console.log(i);
					var id = '#' + v['id'];

					$(id).live('click', function(event, ui) {
						click_button(event, ui, i, v['movex'], v['movey']);
					});
				});

				console.log('done init');
			},
			'start' : function() {
				console.log('start');
				refresh();
			},
			'questions' : function(v) {
				options.questions = v;
			}
		};
	};
})(jQuery);